package me.zhengjie.modules.web.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.util.SignUtils;
import me.zhengjie.config.constant.WeChatConstant;
import me.zhengjie.config.enums.OrderPrefixEnum;
import me.zhengjie.config.exception.WeChatException;
import me.zhengjie.modules.system.domain.ExamOrder;
import me.zhengjie.modules.system.domain.GroupTest;
import me.zhengjie.modules.system.domain.WxUser;
import me.zhengjie.modules.system.service.AtmrService;
import me.zhengjie.modules.system.service.ExamOrderService;
import me.zhengjie.modules.system.service.GroupTestService;
import me.zhengjie.modules.system.service.WxUserService;
import me.zhengjie.modules.system.service.dto.AtmrDto;
import me.zhengjie.modules.system.service.dto.ExamOrderDto;
import me.zhengjie.modules.system.service.dto.ExamOrderQueryCriteria;
import me.zhengjie.modules.system.service.dto.GroupTestDto;
import me.zhengjie.modules.web.domain.AtmrOrderRequest;
import me.zhengjie.modules.web.domain.AtmrOrderResponse;
import me.zhengjie.modules.web.domain.OrderPayRequest;
import me.zhengjie.modules.web.domain.ReturnPayInfoVO;
import me.zhengjie.modules.web.service.IAtmrOrderService;
import me.zhengjie.modules.weixin.utils.OrderUtil;
import me.zhengjie.utils.SnowflakeIdWorker;
import me.zhengjie.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.net.InetAddress;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class AtmrOrderServiceImpl implements IAtmrOrderService {
    private static final Logger log = LoggerFactory.getLogger(AtmrOrderServiceImpl.class);
    @Autowired
    private ExamOrderService orderService;

    @Autowired
    private AtmrService atmrService;

    @Autowired
    private SnowflakeIdWorker snowflakeIdWorker;

    @Autowired
    private WxPayService wxPayService;

    @Autowired
    private GroupTestService groupTestService;

    @Autowired
    WxUserService wxUserService;

    @Override
    public AtmrOrderResponse createOrder(AtmrOrderRequest request) {
        if (StringUtils.isBlank(request.getAtmrId()) || request.getOrderAmount() == null){
            throw new WeChatException("缺少参数");
        }
        AtmrDto atmrDto = atmrService.findById(Integer.parseInt(request.getAtmrId()));
        if (null == atmrDto){
            throw new WeChatException("atmrId 不存在");
        }
        if (null != request.getOrderType()){
            if (request.getOrderType() == 1){
                if (new BigDecimal(atmrDto.getPrice()).compareTo(request.getOrderAmount()) != 0){
                    throw new WeChatException("订单金额传递有误");
                }
            }else {
                if (new BigDecimal(atmrDto.getReportPrice()).compareTo(request.getOrderAmount()) != 0){
                    throw new WeChatException("订单金额传递有误");
                }
            }
        }
        String orderPrefix = OrderPrefixEnum.Normal.getPrefix();
        //团体测评
        int limitUsed = 0;
        boolean updateGroupStock = false;
        if (request.getGroupId() != null){
            GroupTestDto groupTestDto = groupTestService.findById(request.getGroupId());
            if (null == groupTestDto){
                throw new WeChatException("团体测评ID传递有误");
            }
            Timestamp now = new Timestamp(System.currentTimeMillis());
            Timestamp validityFrom = groupTestDto.getValidityFrom();
            Timestamp validityTo = groupTestDto.getValidityTo();
            if (validityFrom.after(now) || validityTo.before(now)){
                throw new WeChatException("团体测评未开始或者已结束");
            }
            Integer limit = groupTestDto.getLimitNum();
            limitUsed = groupTestDto.getLimitUsed();
            if (limitUsed >= limit){
                throw new WeChatException("团体测评次数已用完");
            }
            ExamOrderQueryCriteria criteria = new ExamOrderQueryCriteria();
            if(request.getGroupId() != null) {
                criteria.setTeamTestid(request.getGroupId());
            }
            else
            {
                criteria.setTeamTestid(0);
            }
            criteria.setOpenId(request.getOpenId());
            //criteria.setBeAnswer(1);
            List<ExamOrderDto> examOrderDtos = orderService.queryAll(criteria);
            if (CollectionUtil.isNotEmpty(examOrderDtos)){
                ExamOrderDto examOrderDto = examOrderDtos.parallelStream().filter(s -> s.getBeAnswer() == 1).findFirst().orElse(null);
                if (null != examOrderDto){
                    throw new WeChatException("不要贪心哦,你已经测过一次了");
                }
            }else {
                updateGroupStock = true;
            }
            orderPrefix = OrderPrefixEnum.Free.getPrefix();
        }
        String orderSn = orderPrefix + snowflakeIdWorker.nextId();
        ExamOrder examOrder = new ExamOrder();
        examOrder.setOrderAmount(request.getOrderAmount());
        examOrder.setAtmrId(request.getAtmrId());
        examOrder.setOpenId(request.getOpenId());
        examOrder.setOrderNo(orderSn);
        examOrder.setTeamTestid(request.getGroupId());
        examOrder.setBeAnswer(0);
        examOrder.setCreateTime(Timestamp.valueOf(LocalDateTime.now()));
        examOrder.setPayStatus(0);
        examOrder.setOrderStatus(0);
        examOrder.setPayAmount(BigDecimal.ZERO);
        examOrder.setDiscountAmount(BigDecimal.ZERO);
        examOrder.setPaySerialid("");
        examOrder.setPrePayid("");
        WxUser wxUser = wxUserService.findByOpenId(request.getOpenId());
        if(!ObjectUtil.isEmpty(wxUser)){
           examOrder.setWxRealName(wxUser.getRealName());
           examOrder.setWxName(wxUser.getNickname());
        }
        ExamOrderDto examOrderDto = orderService.create(examOrder);
        AtmrOrderResponse response = new AtmrOrderResponse();
        response.setOrderId(examOrderDto.getOrderId());
        response.setOrderSn(orderSn);
        /*if (updateGroupStock && request.getGroupId() != null){
            GroupTest groupTest = new GroupTest();
            groupTest.setId(request.getGroupId());
            groupTest.setLimitUsed(limitUsed + 1);
            groupTestService.update(groupTest);
        }*/
        return response;
    }

    @Override
    public ReturnPayInfoVO unifiedOrder(OrderPayRequest request) {

        ExamOrder one = orderService.findOne(request.getOrderSn());
        if (null == one){
            throw new WeChatException("非法请求");
        }
        WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = new WxPayUnifiedOrderRequest();
        wxPayUnifiedOrderRequest.setOpenid(request.getOpenId());
        wxPayUnifiedOrderRequest.setNotifyUrl(WeChatConstant.notifyUrl);
        wxPayUnifiedOrderRequest.setSpbillCreateIp(InetAddress.getLoopbackAddress().getHostAddress());
        wxPayUnifiedOrderRequest.setBody("ATMR测评费");
        wxPayUnifiedOrderRequest.setTotalFee(one.getOrderAmount().multiply(new BigDecimal(100)).intValue());
        wxPayUnifiedOrderRequest.setOutTradeNo(one.getOrderNo());
        wxPayUnifiedOrderRequest.setTradeType("JSAPI");
        wxPayUnifiedOrderRequest.setOpenid(request.getOpenId());
        WxPayUnifiedOrderResult wxPayUnifiedOrderResult = null;
        try {
            wxPayUnifiedOrderResult = wxPayService.unifiedOrder(wxPayUnifiedOrderRequest);
        } catch (WxPayException e) {
            log.error("调用微信统一创单接口异常",e);
        }
        if (null == wxPayUnifiedOrderResult || StringUtils.isBlank(wxPayUnifiedOrderResult.getPrepayId())){
            throw new WeChatException("支付异常");
        }
        one.setPrePayid(wxPayUnifiedOrderResult.getPrepayId());
        orderService.update(one);
        //组合参数构建支付
        Map<String, String> paySignInfo = new HashMap<>(5);
        String timeStamp = OrderUtil.GetTimestamp();
        String nonceStr = OrderUtil.CreateNoncestr();
        paySignInfo.put("appId", WeChatConstant.appid);
        paySignInfo.put("nonceStr", nonceStr);
        paySignInfo.put("timeStamp", timeStamp);
        paySignInfo.put("signType", "MD5");
        paySignInfo.put("package", "prepay_id=" + wxPayUnifiedOrderResult.getPrepayId());
        String paySign = SignUtils.createSign(paySignInfo, WeChatConstant.partnerKey);
        //组合支付参数
        ReturnPayInfoVO returnPayInfoVO = new ReturnPayInfoVO();
        returnPayInfoVO.setAppId(WeChatConstant.appid);
        returnPayInfoVO.setNonceStr(nonceStr);
        returnPayInfoVO.setPaySign(paySign);
        returnPayInfoVO.setSignType("MD5");
        returnPayInfoVO.setPrepayId(wxPayUnifiedOrderResult.getPrepayId());
        returnPayInfoVO.setTimeStamp(timeStamp);
        return returnPayInfoVO;
    }

    @Override
    public boolean answerUpdate(String openId,String orderSn) {
        if (StringUtils.isAnyBlank(openId,orderSn)){
            return false;
        }
        ExamOrder one = orderService.findOne(orderSn);
        if (null == one){
            throw new WeChatException("非法请求");
        }
        if (!one.getOpenId().equals(openId)){
            throw new WeChatException("不是本人订单");
        }
        if (one.getBeAnswer().equals(1)){
            throw new WeChatException("已答题不需更新");
        }
        if (one.getPayStatus().equals("0")){
            throw new WeChatException("未支付订单不需要更新");
        }
        one.setBeAnswer(1);
        orderService.update(one);
        return true;
    }

    @Override
    public ExamOrderDto getPayedNoAnswerOrder(String openId,String atmrId) {
        ExamOrderQueryCriteria criteria = new ExamOrderQueryCriteria();
        criteria.setPayStatus(1);
        criteria.setOpenId(openId);
        criteria.setBeAnswer(0);
        criteria.setAtmrId(atmrId);
        List<ExamOrderDto> examOrderDtos = orderService.queryAll(criteria);
        if (CollectionUtil.isEmpty(examOrderDtos)){
            return null;
        }
        return examOrderDtos.get(0);
    }

    @Override
    public GroupTestDto verifyGroupTest(Integer groupId, String openId) {
        if (null == groupId || StringUtils.isBlank(openId)){
            return null;
        }
        GroupTestDto groupTestDto = groupTestService.findById(groupId);
        if (null == groupTestDto){
            throw new WeChatException("团体测评ID传递有误");
        }
        Timestamp now = new Timestamp(System.currentTimeMillis());
        Timestamp validityFrom = groupTestDto.getValidityFrom();
        Timestamp validityTo = groupTestDto.getValidityTo();
        if (validityFrom.after(now) || validityTo.before(now)){
            throw new WeChatException("团体测评未开始或者已结束");
        }
        Integer limit = groupTestDto.getLimitNum();
        Integer limitUsed = groupTestDto.getLimitUsed();
        if (limitUsed >= limit){
            throw new WeChatException("团体测评次数已用完");
        }
        ExamOrderQueryCriteria criteria = new ExamOrderQueryCriteria();
        criteria.setTeamTestid(groupId);
        criteria.setOpenId(openId);
        criteria.setBeAnswer(1);
        List<ExamOrderDto> examOrderDtos = orderService.queryAll(criteria);
        if (CollectionUtil.isNotEmpty(examOrderDtos)){
            throw new WeChatException("不要贪心哦,你已经测过一次了");
        }
        return groupTestDto;
    }
}
